package com.enterprise.support.utility.generator.pub;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;

/**
 * @author ChunBiao Guo
 */
public class MemoryStatus extends JComponent implements ActionListener {

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().setLayout(new BorderLayout());
        JPanel panel = new JPanel();
        frame.getContentPane().add(panel, BorderLayout.CENTER);
        MemoryStatus status = new MemoryStatus(panel);
        panel.setLayout(new BorderLayout());
        panel.add(status, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

    private JComponent parent = null;

    public MemoryStatus(JComponent parentComponent) {
        parent = parentComponent;

        Font font = new JLabel().getFont();
        // Font font = UIManager.getFont("Label.font");
        MemoryStatus.this.setFont(font);

        FontRenderContext frc = new FontRenderContext(null, false, false);
        Rectangle2D bounds = font.getStringBounds(memoryTestStr, frc);
        Dimension dim = new Dimension((int) bounds.getWidth(), (int) bounds
                .getHeight());
        setPreferredSize(dim);
        setMaximumSize(dim);
        lm = font.getLineMetrics(memoryTestStr, frc);

        setForeground(Color.blue);
        setBackground(Color.red);

        progressForeground = Color.blue;
        progressBackground = Color.red;

        addMouseListener(new MouseHandler());
    }

    public void addNotify() {
        super.addNotify();
        timer = new Timer(2000, this);
        timer.start();
        ToolTipManager.sharedInstance().registerComponent(this);
    }

    public void removeNotify() {
        timer.stop();
        ToolTipManager.sharedInstance().unregisterComponent(this);
        super.removeNotify();
    }

    public String getToolTipText() {
        Runtime runtime = Runtime.getRuntime();
        int freeMemory = (int) (runtime.freeMemory() / 1024);
        int totalMemory = (int) (runtime.totalMemory() / 1024);
        int usedMemory = (totalMemory - freeMemory);
        Integer[] args = {new Integer(usedMemory), new Integer(totalMemory)};
        return "view.status.memory-tooltip";
    }

    public Point getToolTipLocation(MouseEvent event) {
        return new Point(event.getX(), -20);
    }

    public void actionPerformed(ActionEvent evt) {
        MemoryStatus.this.repaint();
    }

    public void paintComponent(Graphics g) {
        Insets insets = new Insets(0, 0, 0, 0);// MemoryStatus.this.getBorder().getBorderInsets(this);

        Runtime runtime = Runtime.getRuntime();
        int freeMemory = (int) (runtime.freeMemory() / 1024);
        int totalMemory = (int) (runtime.totalMemory() / 1024);
        int usedMemory = (totalMemory - freeMemory);

        int width = MemoryStatus.this.getWidth() - insets.left - insets.right;
        int height = MemoryStatus.this.getHeight() - insets.top - insets.bottom
                - 1;

        float fraction = ((float) usedMemory) / totalMemory;

        g.setColor(progressBackground);

        g.fillRect(insets.left, insets.top, (int) (width * fraction), height);

        String str = (usedMemory / 1024) + "/" + (totalMemory / 1024) + "Mb";

        FontRenderContext frc = new FontRenderContext(null, false, false);

        Rectangle2D bounds = g.getFont().getStringBounds(str, frc);

        Graphics g2 = g.create();
        g2.setClip(insets.left, insets.top, (int) (width * fraction), height);

        g2.setColor(progressForeground);

        g2.drawString(str, insets.left + (int) (width - bounds.getWidth()) / 2,
                (int) (insets.top + lm.getAscent()));

        g2.dispose();

        g2 = g.create();

        g2.setClip(insets.left + (int) (width * fraction), insets.top,
                MemoryStatus.this.getWidth() - insets.left
                        - (int) (width * fraction), height);

        g2.setColor(MemoryStatus.this.getForeground());

        g2.drawString(str, insets.left + (int) (width - bounds.getWidth()) / 2,
                (int) (insets.top + lm.getAscent()));

        g2.dispose();
    }

    private static final String memoryTestStr = "999/999Mb";

    private LineMetrics lm;

    private Color progressForeground;

    private Color progressBackground;

    private Timer timer;

    class MouseHandler extends MouseAdapter {
        public void mousePressed(MouseEvent evt) {
            if (evt.getClickCount() == 2) {
                showMemoryDialog();
                repaint();
            }
        }
    }

    public void showMemoryDialog() {
        Runtime rt = Runtime.getRuntime();
        int before = (int) (rt.freeMemory() / 1024);
        System.gc();
        int after = (int) (rt.freeMemory() / 1024);
        int total = (int) (rt.totalMemory() / 1024);

        JProgressBar progress = new JProgressBar(0, total);
        progress.setValue(total - after);
        progress.setStringPainted(true);
        progress.setString("memory-status.use: " + new Integer(total - after)
                + ", " + new Integer(total));

        Object[] message = new Object[4];
        message[0] = "memory-status.gc: " + new Integer(after - before);
        message[1] = Box.createVerticalStrut(12);
        message[2] = progress;
        message[3] = Box.createVerticalStrut(6);

        JOptionPane.showMessageDialog(parent, message, "memory-status.title",
                JOptionPane.INFORMATION_MESSAGE);
    }

} 
